// Copyright 2022 jeff.li. and/or its affiliates.

#pragma once

#include <type_traits>
#include <typeindex>

#include <tbir/runtime/container/_flat_hash_map.h>
#include <tbir/runtime/container/string_view.h>

namespace tbir::runtime {

    struct TypeNameTraits {
        TURBO_EXPORT static TypeNameTraits &Register(std::type_index ty_idx, string_view name);

        TURBO_EXPORT static string_view Get(std::type_index ty_idx);

        template<class T>
        inline static TypeNameTraits &Register(string_view name) {
            return Register(typeid(T), name);
        }

        template<class T>
        inline static string_view Get() {
            return Get(typeid(T));
        }

    private:
        // Internal class.
        struct Manager;

        TypeNameTraits() = default;

        ~TypeNameTraits() = default;

        ska::flat_hash_map <std::type_index, string_view> type_info_;
        friend struct Manager;
    };

#define TBIR_TYPE_NAME_TRAITS_VAR_DEF(T) \
  static TURBO_ALLOW_UNUSED auto& __make_##TBIR_TYPE_TRAITS##T

#define TBIR_REGISTER_TYPE_NAME_TRAITS(T)                                \
  TURBO_CONCAT(TBIR_TYPE_NAME_TRAITS_VAR_DEF(T), __COUNTER__) = \
      ::tbir::runtime::TypeNameTraits::Register<T>(#T)

}  // namespace tbir::runtime
